home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Utilities / Winter Shell 1.0d2 / Source / Libraries / FileLib / FileLib.c < prev    next >
Encoding:
Text File  |  1994-01-17  |  13.9 KB  |  397 lines  |  [TEXT/KAHL]

  1. /*    File Library implements a reasonable interface to the more
  2.     commonly used features of the Macintosh's Heirarchical File System.
  3.     This library requires at least System software version 6.0, and
  4.     supports some of the features of system 7.0.
  5.     
  6.     I wrote File Library to address the problems posed by working
  7.     on a file system which uses at least four different methods to
  8.     refer to an unopened file: volume reference number, directory
  9.     ID, partial pathname, and full pathname. Also, the standard
  10.     functions provided by Apple do not have a uniform calling method.
  11.     These "PB" functions pass data via parameter blocks, the required
  12.     fields of which can be difficult to remember, whereas prototyped
  13.     functions guarantee that the correct number and type of arguments
  14.     are being used. All functions, types, and constants defined by
  15.     File Library are prefixed with the letters "File", and the first
  16.     parameter is almost always a pointer to a FileType structure.
  17.     Also, all functions use C format strings (except for a few glue
  18.     functions), so you never have to worry about Pascal format strings.
  19.     
  20.     To use File Library, you call one of the functions with the prefix
  21.     "FileSet", passing the initial descriptors of the file (ie, vRefNum,
  22.     dirID, namePtr). This initializes the FileType structure. You can
  23.     then call any of the other functions in File Library simply by
  24.     passing a pointer to the FileType structure. You can open and close
  25.     the file refered to by the FileType structure, and reuse the same
  26.     FileType structure any number of times.
  27.             
  28.     A set of typedef's for declaring variables such as file names, volume
  29.     reference numbers, and directory IDs are used throughout. I simply find
  30.     it hard to remember if a directory ID is a LongInt or an Integer (it's
  31.     a LongInt), or if a volume reference is a LongInt (it's an Integer). In
  32.     fact, MacDTS also has problems remembering: several of their TechNotes
  33.     use LongInts for working directory numbers while other TechNotes use
  34.     Integers. Use of the new types eliminates this problem.
  35.     
  36.     Since all the references to files are concentrated in this one library,
  37.     it will be simpler to adapt programs to use the new features soon to be
  38.     released in System 7.0. For instance, Apple promises that there will be
  39.     a unique 32-bit integer associated with each file, so that applications
  40.     can always locate the file, regardless of where it is placed. Modifying
  41.     File Library for this new feature is a trivial task, while the alternative
  42.     of wading through hundreds of subroutines with individual declarations
  43.     for the vRefNum, dirID, refNum, namePtr, etc. would be somewhat more
  44.     difficult.
  45.     
  46.     I recently adapted File Library to use the Alias Manager of system 7.0.
  47.     By placing a few calls to MakeFSSpec and ResolveAliasFile, I almost
  48.     completely avoided the headache of adapting to file aliases. All my
  49.     applications were thus immediately able to work happily with system
  50.     7.0. Because File Library serves as an interface between the
  51.     application and the Macintosh file system, it is easier to adapt to
  52.     extensions to the file system by making the modifications in only one
  53.     place, instead of throughout the application.
  54.     
  55.     File Library was developed using THINK C 4.0.4, and doesn't have
  56.     "#include" statements for any of the Macintosh managers (since
  57.     the information is preloaded and included by THINK C). File
  58.     Library should be portable to MPW after appropriate "#include"
  59.     statements are added. The precompiled header I use for system
  60.     7.0 development contains all of the interface files distributed
  61.     with system 7.0. I've been careful to use short integers wherever
  62.     a 2 byte value is called for (regular integers are 2 bytes in
  63.     THINK C and 4 bytes in MPW).
  64.     
  65.     Several functions check whether two files are on the same volume.
  66.     This is done simply by comparing the 'vol' field of two file
  67.     structures. Two files may be on the same volume yet be specified
  68.     using two different working directories, but File Library doesn't
  69.     normally evaluate working directories. For this reason, you should
  70.     avoid using working directories in file structures. You can use
  71.     FileSetWD to convert a working directory into a real volume reference
  72.     number and directory ID, or, in system software which supports the Alias
  73.     Manager and the MakeFSSpec routine (ie, system 7.0 or later), you may
  74.     be able to use any of the FileSet functions [this needs to be tested].
  75.     For instance, the function MacSysVRef returns the working directory of
  76.     the system folder (we are not concerned with MFS volumes), so you should
  77.     use FileSetSys if you want to access a file in the System folder.
  78.     
  79.     Revision History:
  80.     
  81.     93/11/03
  82.     - removed slow file structure validation operations
  83.     
  84.     93/10/16
  85.     - Decreased size of file names to 32 instead of 63. This means structres
  86.     of type FileType can no longer be cast directly to structures of type
  87.     FSSpec, though it does save memory. Since the maximum length of a file
  88.     or directory name is 31, and of a volume name is 27, this should work
  89.     ok.
  90.     - removed FileVolNmType, FilePVolNmType
  91.     
  92.     93/10/14 aih
  93.     - eliminated some rarely used functions
  94.     
  95.     93/03/25 AIH
  96.     - Added check for FindFolder before calling it
  97.     
  98.     93/03/10 AIH
  99.     - Added a not-null check to the function used to validate a structure
  100.     of type FileType
  101.     - Added checks for compatability with systems prior to 7.0
  102.     
  103.     91/11/16 AIH
  104.     - Removed compatability with systems prior to 7.0
  105.     
  106.     91/07/03 AIH
  107.     - Fixed a few obscure bugs in several of the FileSet... functions
  108.     - Clarified a few comments
  109.     
  110.     91/06/06 AIH
  111.     - Modified file for setting location of temporary files to use a prefered
  112.     volume and directory
  113.     - Added function to set a file's location in the extensions folder
  114.     
  115.     91/05/31 AIH
  116.     - Fixed a stupid bug which caused an infinite recursive loop when
  117.     setting a file. I must have been asleep when I introduced the bug.
  118.     
  119.     91/05/27 AIH
  120.     - Added a few more comments and one precondition
  121.     
  122.     91/05/16-17 AIH
  123.     - Added a few comments
  124.     - Fixed a very minor bug
  125.     - Added function for setting a file in the system folder
  126.     
  127.     91/05/09 AIH
  128.     - Fixed a few bugs and places where errors were ignored
  129.     
  130.     91/05/08 AIH
  131.     - Fixed a few problems resolving aliases
  132.     - Added a few comments
  133.     
  134.     91/04/20-21 AIH
  135.     - Added functions for setting temporary and preferences file locations,
  136.     and enhanced the file setting function to use the resolve alias feature
  137.     of system 7.0
  138.     - Reordered internal fields of FileType structure to correspond to
  139.     first three fields of an FSSpec structure
  140.     - Added functions to allow use of FSSpec structures with this library
  141.     - FileSet can return an error code if FileResolve fails
  142.     
  143.     91/03/17 AIH
  144.     - To aid the THINK C linker and to make segmentation possible
  145.     I've split this file into several pieces.
  146.     
  147.     91/03/07 AIH
  148.     - Added functions to do range locking
  149.     - Added lock attribute, which, when enabled, will automatically lock the
  150.     range in a file before data are written to it. This will be expanded
  151.     in the future to include PBRead and SetEOF operations as well.
  152.     - When copying the data fork of a file, the file is truncated with SetEOF
  153.     instead of deleting the destination and then creating it
  154.     
  155.     91/03/02-03 AIH
  156.     - Found TN126 which describes how to use PBCatMove
  157.     - Changed size of FileNameType to use only 32 bytes, which is enough
  158.     to store the longest possible file or directory name
  159.     - A local function is used to set the a file pointer's name field,
  160.     instead of copying into the name fields wherever the name changed
  161.     
  162.     91/02/23 AIH
  163.     - Moved function for testing if a file is already open from
  164.     "PatchGetNextEvent.c" into this library.
  165.     
  166.     91/02/06 AIH
  167.     - The function FileUnique has been improved
  168.     
  169.     91/02/05 AIH
  170.     - Updated Finder flags
  171.     - Added FilePathType, FilePPathType, FileVolNmType, FilePVolNmType
  172.     - Removed FileCloseRes function since it was identical to FileClose
  173.     
  174.     91/01/28 AIH
  175.     - Added FileErase, which will overwrite an existing file with zeroes.
  176.     This ensures that the file is completely deleted.
  177.     
  178.     91/01/24 AIH
  179.     - Added functions for getting all the finder info about files and
  180.     folders
  181.     - Moved archiving functions into a separate file so as to avoid
  182.     needing the library ResourceLib which itself uses this library, resulting
  183.     in an ugly circular reference
  184.     - Moved header comments out of FileLib.h and into this file to avoid
  185.     duplication of information
  186.     - Added defines for the various finder flags
  187.     
  188.     91/01/21 AIH
  189.     - Defined FileNameType and FilePNameType.
  190.     
  191.     91/01/13 AIH
  192.     - Continuing to improve this library
  193.     
  194.     90/11/14 AIH
  195.     - Fixed indirect file references. Updated version number, added some
  196.     string reading and writing functions.
  197.         
  198.     90/11/12    Ari Halberstadt (AIH)
  199.     - Created this library. Archiving method was original reason for
  200.     writing it. */
  201.  
  202. #include <limits.h>
  203. #include <string.h>
  204. #include <Aliases.h>
  205. #include <Finder.h>
  206. #include <Folders.h>
  207. #include "pstr.h"
  208. #include "MacLib.h"
  209. #include "MemoryLib.h"
  210. #include "StringLib.h"
  211. #include "FileLib.h"
  212.                           
  213. /*----------------------------------------------------------------------------*/
  214. /* validating a file structure */
  215. /*----------------------------------------------------------------------------*/
  216.  
  217. /* true if a valid file structure */
  218. Boolean FileValid(FileType *fp)
  219. {
  220.     if (! fp) return(false);
  221.     if (*fp->pnm >= sizeof(FilePNameType)) return(false);
  222.     /* The following two conditions must hold but are too slow to evaluate.
  223.         if (strlen(fp->cnm) != *fp->pnm) return(false);
  224.        if (memcmp(fp->cnm, fp->pnm + 1, *fp->pnm) != 0) return(false); */
  225.     return(true);
  226. }
  227.  
  228. /*----------------------------------------------------------------------------*/
  229. /* setting up a file structure */
  230. /*----------------------------------------------------------------------------*/
  231.  
  232. /* clone the file's specification (except for the refnum) */
  233. void FileClone(FileType *src, FileType *dst)
  234. {
  235.     require(FileValid(src));
  236.     *dst = *src;
  237.     dst->ref = FILE_CLOSED;
  238. }
  239.  
  240. /* return a pointer to the name of the file */
  241. const char *FileName(FileType *fp)
  242. {
  243.     require(FileValid(fp));
  244.     return(fp->cnm);
  245. }
  246.  
  247. /* set the file's name; you may want to call FileResolve after calling
  248.     this function */
  249. void FileNameSet(FileType *fp, const FileNameType name)
  250. {
  251.     require(StrValid(name, sizeof(FileNameType)));
  252.     strcpy(fp->cnm, name);
  253.     c2pstrcpy(fp->pnm, name);
  254. }
  255.  
  256. /* convert the file structure to an FSSpec */
  257. void FileToFSSpec(FileType *fp, FSSpec *spec)
  258. {
  259.     OSErr err = noErr;
  260.     
  261.     require(FileValid(fp));
  262.     require(MacHasFSSpec());
  263.     err = FSMakeFSSpec(fp->vol, fp->dir, fp->pnm, spec);
  264.     if (err == fnfErr)
  265.         err = noErr;
  266.     FailOSErr(err);
  267. }
  268.  
  269. /* Resolve the file's alias, or do nothing if the Alias Manager is unavailable.
  270.     This function is always called after any of the file setting functions
  271.     are called, so there is usually no need for your application to call this
  272.     function directly. (Hooray for data hiding!) */
  273. void FileResolve(FileType *fp)
  274. {
  275.     FSSpec spec;
  276.     Boolean folder;
  277.     Boolean aliased;
  278.     OSErr err;
  279.     
  280.     if (MacHasAliases()) {
  281.         FileToFSSpec(fp, &spec);
  282.         err = ResolveAliasFile(&spec, true, &folder, &aliased);
  283.         if (err == fnfErr)
  284.             err = noErr;
  285.         FailOSErr(err);
  286.         fp->vol = spec.vRefNum;
  287.         fp->dir = spec.parID;
  288.         FileNameSet(fp, p2cstr(spec.name));
  289.     }
  290. }
  291.  
  292. /* set the file's identifier */
  293. void FileSet(FileType *fp, FileVolType vol, FileDirType dir,
  294.     const FileNameType name)
  295. {
  296.     require(name != fp->cnm); /* this is to avoid a possible (stupid) bug */
  297.     memclr(fp, sizeof(FileType));
  298.     fp->vol = vol;
  299.     fp->dir = dir;
  300.     FileNameSet(fp, name);
  301.     FileResolve(fp);
  302.     ensure(FileValid(fp));
  303. }
  304.  
  305. /* This function is equivalent to FileSet, except that it takes
  306.     a working directory ID instead of a volume reference number
  307.     and a directory ID. This function is most useful when accessing
  308.     a file selected using the Standard File package. */
  309. void FileSetWD(FileType *fp, FileWDirType wdref, const FileNameType name)
  310. {
  311.     FileVolType vol;
  312.     FileDirType dir;
  313.     long procid;
  314.  
  315.     FailOSErr(GetWDInfo(wdref, &vol, &dir, &procid));
  316.     FileSet(fp, vol, dir, name);
  317. }
  318.  
  319. /* this is the same as FileSet, except it takes the reference number of an
  320.     open file */
  321. void FileSetRef(FileType *fp, FileRefType ref)
  322. {
  323.     FCBPBRec pb;
  324.     FileNameType name;
  325.     
  326.     *name = 0;
  327.     memclr(&pb, sizeof(FCBPBRec));
  328.     pb.ioNamePtr = (StringPtr) name;
  329.     pb.ioRefNum = ref;
  330.     FailOSErr(PBGetFCBInfo(&pb, false));
  331.     FileSet(fp, pb.ioFCBVRefNum, pb.ioFCBParID, p2cstr((StringPtr) name));
  332. }
  333.  
  334. /* this is identical to FileSet except the file's specification is taken
  335.     from an FSSpec structure */
  336. void FileSetFSSpec(FileType *fp, const FSSpec *spec)
  337. {
  338.     FileNameType name;
  339.     FileSet(fp, spec->vRefNum, spec->parID, p2cstrcpy(name, spec->name));
  340. }
  341.  
  342. /* This is similar to FileSet, except that it takes only the name of a
  343.     file, and sets the file's location to the system folder. */
  344. void FileSetSys(FileType *fp, const FileNameType name)
  345. {
  346.     FileVolType vol = MacSysVRef();
  347.     FileDirType dir = 0;
  348.     
  349.     if (MacHasFindFolder()) {
  350.         FailOSErr(FindFolder(kOnSystemDisk, kSystemFolderType, 
  351.                                     kDontCreateFolder, &vol, &dir));
  352.     }
  353.     FileSet(fp, vol, dir, name);
  354. }
  355.  
  356. /* This is similar to FileSet, it places the file in the
  357.     temporary items folder on the specified volume. The FileUnique
  358.     function is then called to ensure that the file's name is
  359.     unique in that directory. */
  360. void FileSetTemp(FileType *fp)
  361. {
  362.     require(FileValid(fp));
  363.     if (MacHasFindFolder()) {
  364.         FailOSErr(FindFolder(fp->vol, kTemporaryFolderType, kCreateFolder,
  365.                                     &fp->vol, &fp->dir));
  366.     }
  367.     FileUnique(fp);
  368. }
  369.  
  370. /* This is similar to FileSet, except it takes only the name of a file and
  371.     sets the file in the preferences folder. */
  372. void FileSetPref(FileType *fp, const FileNameType name)
  373. {
  374.     FileVolType vol = MacSysVRef();
  375.     FileDirType dir = 0;
  376.     
  377.     if (MacHasFindFolder()) {
  378.         FailOSErr(FindFolder(kOnSystemDisk, kPreferencesFolderType,
  379.                                     kCreateFolder, &vol, &dir));
  380.     }
  381.     FileSet(fp, vol, dir, name);
  382. }
  383.  
  384. /* This is similar to FileSet, except it takes only the name of a file, and
  385.     sets the file in the extensions folder. */
  386. void FileSetExtension(FileType *fp, const FileNameType name)
  387. {
  388.     FileVolType vol = MacSysVRef();
  389.     FileDirType dir = 0;
  390.     
  391.     if (MacHasFindFolder()) {
  392.         FailOSErr(FindFolder(kOnSystemDisk, kExtensionFolderType,
  393.                                     kCreateFolder, &vol, &dir));
  394.     }
  395.     FileSet(fp, vol, dir, name);
  396. }
  397.